%{
#include <stdio.h>
#include <stdlib.h>

int yydebug = 0;  // 调试标志
int yylex();
void yyerror(const char *s);
%}

%token MAIN CONST INT BREAK CONTINUE IF ELSE
%token WHILE GETINT PRINTF RETURN VOID
%token IDENT INT_CONST STR_CONST
%token COMMA SEMICN ASSIGN LPARENT RPARENT LBRACE RBRACE LBRACK RBRACK
%token NOT AND OR PLUS MINU MULT DIV MOD LSS LEQ GRE GEQ EQL NEQ

%left PLUS MINU
%left MULT DIV MOD
%left LSS LEQ GRE GEQ
%left EQL NEQ
%right AND OR
%right NOT

%right UMINUS UPLUS

%%

CompUnit
    : GLOBL_DeclList MainFuncDef {
        printf("<CompUnit>\n");
    }
    ;

GLOBL_DeclList
    : /* 空 */
    | GLOBL_DeclList Decl {
        // 处理多个声明
    }
    | GLOBL_DeclList FuncDef {

    }
    ;

Decl :
    ConstDecl {
        if(yydebug)
        printf("<Decl>\n");
    } 
    | VarDecl {
        if(yydebug)
        printf("<Decl>\n");
    }
    ; 
    

FuncDef :
    BType IDENT LPARENT ParamList RPARENT Block {
        
        printf("<FuncDef>\n");
    }
    ;

ParamList :
    Param {
        // 处理单个参数
    } | ParamList COMMA Param {
        // 处理多个参数
    }
    ;

Param :
    BType IDENT {
        if(yydebug)
        printf("<Param: Parameter>\n");
    }
    ;


ConstDecl :
    CONST BType VarDeclList SEMICN {
        printf("<ConstDecl>\n");
    }
    ;

MainFuncDef :
    INT MAIN LPARENT RPARENT Block {
        printf("<MainFuncDef>\n");
    }
    ;

Block :
    LBRACE BlockItems RBRACE {
        printf("<Block>\n");
    }
    ;


BlockItems :
    BlockItems BlockItem {
        // 处理 BlockItems
    } | /* 空 */
    ;

BlockItem :
    Decl {
        // 处理 BlockItem
         if(yydebug)
        printf("In BlockItem\n");
    } | Stmt {
        // 处理 BlockItem
         if(yydebug)
        printf("In BlockItem Stmt\n");
    }
    ;

Stmt :
    SEMICN {
        printf("<Stmt>\n");
    }
    | Expr SEMICN {
        printf("<Stmt>\n");
    }
    | Assignment SEMICN {
        printf("<Stmt>\n");
    }
    | Block {
        printf("<Stmt>\n");
    }
    | RETURN Expr SEMICN {
        printf("<Stmt>\n");
    }
    |WHILE LPARENT Expr RPARENT Block {
        printf("<Stmt>\n");
    }
    | IF LPARENT Expr RPARENT Stmt {
        printf("<Stmt>\n");
    }
    | IF LPARENT Expr RPARENT Stmt ELSE Stmt{
        printf("<Stmt>\n");
    }
    ;

Assignment :
    IDENT ASSIGN Expr {
         if(yydebug)
        printf("<Assignment: Simple Variable>\n");
    }
    | IDENT LBRACK Expr RBRACK ASSIGN Expr {
         if(yydebug)
        printf("<Assignment: Array Element>\n");
    }
    ;


FUNCTION_CALL:
    GETINT LPARENT RPARENT {
         if(yydebug)
        printf("<Expr: GETINT Function Call>\n");
    }
    | PRINTF LPARENT STR_CONST RPARENT {
         if(yydebug)
        printf("<Expr: PRINTF Function Call>\n");
    }
    | PRINTF LPARENT STR_CONST COMMA ExprList RPARENT {
         if(yydebug)
        printf("<Expr: PRINTF Function Call>\n");
    }
    | IDENT LPARENT ExprList RPARENT {
         if(yydebug)
        printf("<Expr: Function Call>\n");
    }
    ;

Expr :
    FUNCTION_CALL {
        if(yydebug)        
        printf("<Expr: FUNCTION_CALL>\n");
    }   
    | INT_CONST {
         if(yydebug)
        printf("<Expr: INT_CONST>\n");
    }
    | IDENT {
         if(yydebug)
        printf("<Expr: IDENT>\n");
    }
    | IDENT LBRACK Expr RBRACK {
         if(yydebug)
        printf("<Expr: Array Element Access>\n");
    }
    | Expr PLUS Expr {
        if(yydebug)
        printf("<Expr: Addition>\n");
    }
    | Expr MINU Expr {
        if(yydebug)
        printf("<Expr: Subtraction>\n");
    }
    | MINU Expr %prec UMINUS {
        if(yydebug)
        printf("<Expr: Unary Minus>\n");
    }
    | PLUS Expr %prec UPLUS {
        if(yydebug)
        printf("<Expr: Unary Plus>\n");
    }
    | Expr MULT Expr {
         if(yydebug)
        printf("<Expr: Multiplication>\n");
    }
    | Expr DIV Expr {
         if(yydebug)
        printf("<Expr: Division>\n");
    }
    | Expr MOD Expr {
         if(yydebug)
        printf("<Expr: Modulo>\n");
    }
    | Expr LSS Expr {
         if(yydebug)
        printf("<Expr: Less Than>\n");
    }
    | Expr GRE Expr {
         if(yydebug)
        printf("<Expr: Greater Than>\n");
    }
    | Expr LEQ Expr {
         if(yydebug)
        printf("<Expr: Less Than or Equal>\n");
    }
    | Expr GEQ Expr {
         if(yydebug)
        printf("<Expr: Greater Than or Equal>\n");
    }
    | Expr EQL Expr {
         if(yydebug)
        printf("<Expr: Equal>\n");
    }
    | Expr NEQ Expr {
         if(yydebug)
        printf("<Expr: Not Equal>\n");
    }
    | Expr AND Expr {
         if(yydebug)
        printf("<Expr: Logical AND>\n");
    }
    | Expr OR Expr {
         if(yydebug)
        printf("<Expr: Logical OR>\n");
    }
    | NOT Expr {
         if(yydebug)
        printf("<Expr: Logical NOT>\n");
    }
    | LPARENT Expr RPARENT {
         if(yydebug)
        printf("<Expr: Parentheses>\n");
    }
    ;


ExprList :
    Expr {
         if(yydebug)
        printf("<ExprList: Single Expression>\n");
    }
    | ExprList COMMA Expr {
         if(yydebug)
        printf("<ExprList: Multiple Expressions>\n");
    }
    ;

VarDecl :
    BType VarDeclList SEMICN {
        
        printf("<VarDecl>\n");
    }
    ;

VarDeclList :
    VarDeclItem {
        // 处理单个变量或数组声明
    }
    | VarDeclList COMMA VarDeclItem {
        // 处理多个变量或数组声明
    }
    ;

VarDeclItem :
    IDENT {
         if(yydebug)
        printf("<VarDeclItem: Simple Variable>\n");
    }
    | IDENT ASSIGN Expr {
         if(yydebug)
        printf("<VarDeclItem: Variable with Initialization>\n");
    }
    | IDENT LBRACK INT_CONST RBRACK {
 if(yydebug)        
        printf("<VarDeclItem: Array>\n");
    }
    | IDENT LBRACK INT_CONST RBRACK ASSIGN LBRACE ExprList RBRACE{
         if(yydebug)
        printf("<VarDeclItem: Array with Initialization>\n");
    }
    ;

BType : 
    INT {
        // 处理 BType
    } |
    VOID {
        // 处理 BType
    }
    ;


%%

int main() {
    #ifdef DEBUG
    yydebug = 1;  // 1为启用调试，0为不启用调试
    #endif
    return yyparse();
}

void yyerror(const char *s){
    printf("error:%s\n",s);
}